/* ***** BEGIN LICENSE BLOCK *****
 *   Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is EasySNAV.
 *
 * The Initial Developer of the Original Code is
 * Antonio Gomes (tonikitoo) <tonikitoo@gmail.com>.
 * Portions created by the Initial Developer are Copyright (C) 2008
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

// TODO:
// 1) need to avoid the possibility of set the same value to different modifiers/keyCodes.
// 2) utis.js needs more love.
// 3) ALT works only at first time.

const Cc = Components.classes;
const Ci = Components.interfaces;

// modifier values
const kAlt   = "alt";
const kShift = "shift";
const kCtrl  = "ctrl";
const kNone  = "none";

// PREF NAME || PREF TYPE || IS_GOES_TO_LISTBOX || RANDON_INDEX || DEFAULT_PREF_VALUE || CUR_VALUE
var _enabled =           new Array ("enabled",           "bool", false, 0, false);
var _xulContentEnabled = new Array ("xulContentEnabled", "bool", false, 1, false);
var _kcModifier =        new Array ("keyCode.modifier",  "char", true, 2, kNone);
var _kcUp =              new Array ("keyCode.up",        "int",  true, 3, Ci.nsIDOMKeyEvent.DOM_VK_UP);
var _kcDown =            new Array ("keyCode.down",      "int",  true, 4, Ci.nsIDOMKeyEvent.DOM_VK_DOWN);
var _kcLeft =            new Array ("keyCode.left",      "int",  true, 5, Ci.nsIDOMKeyEvent.DOM_VK_LEFT);
var _kcRight =           new Array ("keyCode.right",     "int",  true, 6, Ci.nsIDOMKeyEvent.DOM_VK_RIGHT);

const prefName = 0;
const type = 1;
const inList = 2;
const index = 3;
const defaultValue = 4;
const value = 5;

var prefs = new Array ();
prefs [_enabled[index]] = _enabled;
prefs [_xulContentEnabled[index]] = _xulContentEnabled;
prefs [_kcModifier[index]] = _kcModifier;
prefs [_kcUp[index]] = _kcUp;
prefs [_kcDown[index]] = _kcDown;
prefs [_kcLeft[index]] = _kcLeft;
prefs [_kcRight[index]] = _kcRight;

var gSnavPrefControl = {

    init: function() {
        this.register();
        this.loadPrefs();
        //gContRow = 0;
        if (prefs)
            prefs.forEach(this.completeList);
        this.colorTable("treechildren_modifiers");
        this.colorTable("treechildren_keycode");
    },

    register: function() {

        this.prefService = Cc["@mozilla.org/preferences-service;1"]
                .getService(Ci.nsIPrefService);

        this._branch = this.prefService.getBranch("snav.");
        this._branch.QueryInterface(Ci.nsIPrefBranch2);
        //this._branch.addObserver("", this, false);
    },

    loadPrefs: function() {

        try {
            prefs[_enabled[index]][value] = this._branch.getBoolPref("enabled");
        } catch(e) {
            prefs[_enabled[index]][value] = false;
        }

        try {
            prefs[_xulContentEnabled[index]][value] = this._branch.getBoolPref("xulContentEnabled");
        } catch(e) {
            prefs[_xulContentEnabled[index]][value] = false;
        }

        try {
            prefs[_kcModifier[index]][value] = this._branch.getCharPref("keyCode.modifier");

            // resetting modifiers
            this.modifierAlt = false;
            this.modifierShift = false;
            this.modifierCtrl = false;

            if (this.keyCodeModifier != this.kNone)
            {
                // use are using '+' as a separator in about:config.
                var mods = prefs[_kcModifier[index]][value].split(/\++/);
                for (var i = 0; i < mods.length; i++) {
                    var mod = mods[i].toLowerCase();
                    if (mod == "")
                        continue;
                    else if (mod == kAlt)
                        this.modifierAlt = true;
                    else if (mod == kShift)
                        this.modifierShift = true;
                    else if (mod == kCtrl)
                        this.modifierCtrl = true;
                    else {
                        prefs[_kcModifier[index]][value] = kNone;
                        break;
                    }
                }
            }
        } catch(e) {
            prefs[_kcModifier[index]][value] = kNone;
        }

        try {
            prefs[_kcUp[index]][value] = this._branch.getIntPref("keyCode.up");
        } catch(e) {
            prefs[_kcUp[index]][value] = Ci.nsIDOMKeyEvent.DOM_VK_UP;
        }
        try {
            prefs[_kcDown[index]][value] = this._branch.getIntPref("keyCode.down");
        } catch(e) {
            prefs[_kcDown[index]][value] = Ci.nsIDOMKeyEvent.DOM_VK_DOWN;
        }

        try {
            prefs[_kcLeft[index]][value] = this._branch.getIntPref("keyCode.left");
        } catch(e) {
            prefs[_kcLeft[index]][value] = Ci.nsIDOMKeyEvent.DOM_VK_LEFT;
        }

        try {
            prefs[_kcRight[index]][value] = this._branch.getIntPref("keyCode.right");
        } catch(e) {
            prefs[_kcRight[index]][value] = Ci.nsIDOMKeyEvent.DOM_VK_RIGHT;
        }
    },

    completeList : function(element, index, array) {

        if (!element[inList])
            return;

        //var editable;
        var treeID;
        if (element[prefName].indexOf("modifier") != -1) {
            treeID = "treechildren_modifiers";
            //editable = false;
        } else {
            treeID = "treechildren_keycode";
            //editable = true;
        }

        var treechildren = document.getElementById(treeID);

        const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
        var treeitem = document.createElementNS(XUL_NS, "treeitem");
        treeitem.setAttribute("container", true);
        treeitem.setAttribute("open", true);
        treeitem.setAttribute("seltype", "single");
        treeitem.setAttribute("pos", index);

        var treerow = document.createElementNS(XUL_NS, "treerow");

        var treecell1 = document.createElementNS(XUL_NS, "treecell");
        treecell1.setAttribute("label", element[prefName]);

        var treecell2 = document.createElementNS(XUL_NS, "treecell");
        if(element[type] == "char")
            treecell2.setAttribute("label", element[value]);
        else
            if((element[value] >= 48 && element[value] <= 57) ||
               (element[value] >= 97 && element[value] <= 122))
                treecell2.setAttribute("label", gSnavUtils.charCodeToString(element[value]));
               else
                treecell2.setAttribute("label", gSnavUtils.keyCodeToString(element[value]));

        treerow.appendChild(treecell1);
        treerow.appendChild(treecell2);
        treeitem.appendChild(treerow);
        treechildren.appendChild(treeitem);
    },

    onSelect : function(e) {
        this.updateGroupBox();
    },

    onFocus : function(e) {
        this.updateGroupBox();
    },

    onBlur : function(e) {
        this.updateGroupBox();
    },

    onUpdateState : function(e) {
        if(document.getElementById("rg1").selectedIndex == 0) {
            var tree = document.getElementById("treemodifiers");
            var selection = tree.contentView.getItemAtIndex(tree.currentIndex);

            if(prefs[selection.getAttribute("pos")][type] == "char")
                tree.view.setCellText(tree.currentIndex,
                                      tree.columns.getNamedColumn('treecol2'),
                                      prefs[selection.getAttribute("pos")][defaultValue]);
            else
                tree.view.setCellText(tree.currentIndex,
                                      tree.columns.getNamedColumn('treecol2'),
                                      gSnavUtils.keyCodeToString(prefs[selection.getAttribute("pos")][defaultValue]));

            var col1 = prefs[selection.getAttribute("pos")][prefName];
            var col2 = prefs[selection.getAttribute("pos")][defaultValue];

            if(prefs[selection.getAttribute("pos")][type] == "char") {
                this._branch.setCharPref(col1, col2);
                document.getElementById("button1").label = col2;
            } else if(prefs[selection.getAttribute("pos")][type] == "int") {
                this._branch.setIntPref(col1, prefs[selection.getAttribute("pos")][defaultValue]);
                document.getElementById("button1").label =
                            gSnavUtils.charCodeToString(prefs[selection.getAttribute("pos")][defaultValue]);
                // button label
                document.getElementById("button1").label =
                            gSnavUtils.keyCodeToString(prefs[selection.getAttribute("pos")][defaultValue]);
            }

            prefs[selection.getAttribute("pos")][value] =
                        prefs[selection.getAttribute("pos")][defaultValue];

        } else {
            this.onModEdit();
        }
    },

    onModEdit : function(e) {
        // what value is set: default or custom ?
        var tree = document.getElementById("treemodifiers");
        var selection = tree.contentView.getItemAtIndex(tree.currentIndex);

        // if focused item do not have "pos" attr, bail.
        if(!selection.hasAttribute("pos")) {
            rg.disabled = true;
            return ;
        }

        var col1 = tree.view.getCellText(tree.currentIndex, tree.columns.getNamedColumn('treecol1'));
        var col2 = tree.view.getCellText(tree.currentIndex, tree.columns.getNamedColumn('treecol2'));

        var params;
        var isModifier = (col1.indexOf("modifier") != -1);
        params = {inn:{isModifier:isModifier, prefName:col1, prefValue:col2}, out:null};

        document.documentElement.openSubDialog("chrome://snav/content/keyListening.xul", "", params);

        if(params.out) {
            if(isModifier) {
                this._branch.setCharPref(col1, params.out.label);
                prefs[selection.getAttribute("pos")][value] = params.out.label;

                tree.view.setCellText(tree.currentIndex,
                                      tree.columns.getNamedColumn('treecol2'),
                                      params.out.label);
            } else {
                if(params.out.key) {
                    this._branch.setIntPref(col1, parseInt(params.out.key));
                    prefs[selection.getAttribute("pos")][value] = params.out.key;

                    tree.view.setCellText(tree.currentIndex,
                                          tree.columns.getNamedColumn('treecol2'),
                                          params.out.label);
                }
            }
        }
        this.updateGroupBox();
    },

    updateGroupBox : function() {
        // we have a selection so disable radiobox
        var rg = document.getElementById("rg1");
        rg.disabled = false;
        var btn = document.getElementById("button1");
        btn.disabled = false;

        // what value is set ? default ? custom ?
        var tree = document.getElementById("treemodifiers");
        var selection = tree.contentView.getItemAtIndex(tree.currentIndex);
        // if focused item do not have "pos" attr, bail.
        if(!selection.hasAttribute("pos")) {
            rg.disabled = true;
            btn.disabled = true;
            return ;
        }

        var textValue = tree.view.getCellText(tree.currentIndex, tree.columns.getNamedColumn('treecol2'));

        // is default value, update rg accordingly.
        rg.selectedIndex = (prefs[selection.getAttribute("pos")][defaultValue] ==
                            prefs[selection.getAttribute("pos")][value]) ? 0 : 1;

        // button label
        btn.label = textValue;
    },

    colorTable : function(id) {

        var treechildren = document.getElementById(id);
        var treerows = treechildren.getElementsByTagName("treerow");
        for (var i = 0; i < treerows.length; i = i + 2) {
            treerows[i].childNodes[0].setAttribute("properties", "leftWaterMark");
            treerows[i].childNodes[1].setAttribute("properties", "rightWaterMark");
        }
    }
}